﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using ST.Common.Util.Model;
using ST.Common.Util.Security;
using System;
using System.Collections.Generic;
using System.Text;

namespace ST.Common.Util.Mvc
{
	public class HttpContextHelper
	{
		private static IHttpContextAccessor ctxAccessor;


		public static void Configure(IHttpContextAccessor httpContextAccessor)
		{
			ctxAccessor = httpContextAccessor;
		}

		/// <summary>
		/// 当前请求的HttpContext
		/// </summary>
		public static HttpContext Current
		{
			get
			{
				return ctxAccessor.HttpContext;
			}
		}

		/// <summary>
		/// 获取当前请求IP地址
		/// </summary>
		/// <returns></returns>
		public static string GetRequestIP()
		{
			return GetRequestIP(Current);
		}

		/// <summary>
		/// 获取请求IP地址
		/// </summary>
		/// <param name="ctx"></param>
		/// <returns></returns>
		public static string GetRequestIP(HttpContext ctx)
		{
			string ip = string.Empty;
			StringValues ipHdr = ctx.Request.Headers["X-FORWARDED-FOR"];
			if (ipHdr.Count > 0)
			{
				ip = ipHdr[0];
			}
			if (string.IsNullOrEmpty(ip))
			{
				ip = ctx.Connection.RemoteIpAddress.ToString();
			}
			return ip;
		}

		/// <summary>
		/// 功能同GetRawSessionFromRequest，只不过加了一些业务判断。获取当前用户会话信息（先从cookie中读取skey和ucode，如果没有再从header中读取skey和ucode），出错抛出AuthException
		/// </summary>
		/// <param name="req"></param>
		/// <returns></returns>
		public static UserSession GetSessionFromRequest(HttpRequest req, bool cors)
		{
			UserSession session = GetRawSessionFromRequest(req, cors);
			if (session.UserID > 1 && session.OrgID == 0) // 只允许超级管理员可以不维护单位
			{
				throw new AuthException("未维护单位");
			}
			return session;
		}

		/// <summary>
		/// 获取当前用户会话信息（先从cookie中读取skey和ucode，如果没有再从header中读取skey和ucode），出错抛出AuthException
		/// </summary>
		/// <param name="req"></param>
		/// <param name="cors">是否跨站，如果跨站的话不好通过cookie和header传参，只能通过form传递</param>
		/// <returns></returns>
		public static UserSession GetRawSessionFromRequest(HttpRequest req, bool cors)
		{
			UserSession result = null;
			try
			{
				string _skey = string.Empty;
				string _ucode = string.Empty;

				if (cors)
				{
					_skey = req.Form["_skey"];
					_ucode = req.Form["_ucode"];
				}
				else
				{
					_skey = req.Cookies["skey"];
					_ucode = req.Cookies["ucode"];
					if (string.IsNullOrEmpty(_skey) || string.IsNullOrEmpty(_ucode))
					{
						_skey = req.Headers["skey"];
						_ucode = req.Headers["ucode"];
					}
				}

				if (string.IsNullOrEmpty(_skey) || string.IsNullOrEmpty(_ucode))
				{
					throw new AuthException("获取会话信息为空，用户可能未登录或登录已过期");
				}
				string sessionStr = EncryptHelper.AESDecrypt(_skey, _ucode);//会话都是更新之后的
				if (string.IsNullOrEmpty(sessionStr))
				{
					throw new AuthException("解密请求头部认证信息失败，用户可能未登录或登录已过期");
				}
				result = JsonConvert.DeserializeObject<UserSession>(sessionStr);
				if (result == null)
				{
					throw new AuthException("解析请求头部认证信息为空，登录可能已过期");
				}
			}
			catch (AuthException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				throw new AuthException("获取请求头部认证信息失败，用户可能未登录或登录已过期", ex);
			}
			return result;
		}

		/// <summary>
		/// 获取当前请求的完整路径
		/// </summary>
		/// <param name="request"></param>
		/// <returns></returns>
		public static string GetRequestUrl(HttpRequest request)
		{
			return string.Concat(request.Scheme,
							"://",
							request.Host.ToUriComponent(),
							request.PathBase.ToUriComponent(),
							request.Path.ToUriComponent(),
							request.QueryString.ToUriComponent());
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="request"></param>
		/// <returns></returns>
		public static string GetDisplayUrl(HttpRequest request)
		{
			return request.GetDisplayUrl();
		}

		/// <summary>
		/// 获取当前请求的Url前缀（包含PathBase）
		/// </summary>
		/// <param name="request"></param>
		/// <returns></returns>
		public static string GetRequestDomainBase(HttpRequest request)
		{
			return string.Concat(request.Scheme,
							"://",
							request.Host.ToUriComponent(),
							request.PathBase.ToUriComponent());
		}
	}
}
